package com.shadow.demo.excel.easy.excel;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Collection;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.read.listener.ReadListener;
import com.shadow.demo.common.util.EnumUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import cn.hutool.core.date.DatePattern;

/**
 * EasyExcel文档转换、操作工具类.
 */
public final class EasyExcelUtil {

    /** 数据导出Excel默认名称. **/
    private static final String EXCEL_NAME_DEFAULT       = "数据导出列表";
    /** 数据导出Excel的sheet默认名称. **/
    private static final String EXCEL_SHEET_NAME_DEFAULT = "Sheet1";

    private EasyExcelUtil() {
    }

    /**
     * Excel的数据导出.
     * @param response 响应对象
     * @param fileName 文件名称，可空
     * @param excelSuffix excel后缀.xlsx .xls .cvs，可空
     * @param sheetName 默认sheet名称，可空
     * @param voClass 写入的VO配置对象
     * @param dataList 导出的数据列表
     * @throws IOException 抛出IO异常
     **/
    public static void exportData(
            final HttpServletResponse response,
            final String fileName,
            final String excelSuffix,
            final String sheetName,
            final Class<?> voClass,
            final Collection<?> dataList
    ) throws IOException {
        // 文件名追加时间戳
        final String newFileName = StringUtils.defaultIfBlank(fileName, EXCEL_NAME_DEFAULT)
                + LocalDateTime.now().format(DatePattern.PURE_DATETIME_FORMATTER);
        // 设置响应参数
        final String newExcelSuffix = StringUtils.defaultIfBlank(excelSuffix, ExcelSuffixEnum.XLSX.getValue());
        response.reset();
        response.setHeader(
                "Content-disposition",
                String.format(
                        "attachment; filename=%s%s",
                        new String(newFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1),
                        newExcelSuffix
                )
        );
        response.setContentType("application/msexcel");
        // 指定写用哪个class去写，默认写到第一个sheet并指定名称，然后执行分页查询并写入数据到Excel导出，最后文件流会自动关闭。
        final ExcelSuffixEnum excelSuffixEnum = ObjectUtils.defaultIfNull(
                EnumUtil.getByValue(ExcelSuffixEnum.class, newExcelSuffix),
                ExcelSuffixEnum.XLSX
        );
        EasyExcelFactory.write(response.getOutputStream(), voClass)
                .excelType(excelSuffixEnum.getExcelTypeEnum())
                .sheet(StringUtils.defaultIfBlank(sheetName, EXCEL_SHEET_NAME_DEFAULT))
                .doWrite(() -> dataList);
    }

    public static void importData(
            final String fileName,
            final String sheetName,
            final Class<?> clazz,
            final ReadListener<?> listener
    ) {
        EasyExcelFactory.read(fileName, clazz, listener)
                .sheet(StringUtils.defaultIfBlank(sheetName, EXCEL_SHEET_NAME_DEFAULT))
                .doRead();
    }

    public static String importData(
            final InputStream inputStream,
            final String sheetName,
            final Class<?> clazz,
            final ReadListener<?> listener
    ) {
        try {
            EasyExcelFactory.read(inputStream, clazz, listener)
                    .sheet(StringUtils.defaultIfBlank(sheetName, EXCEL_SHEET_NAME_DEFAULT))
                    .doRead();
        } catch (MyExcelException e) {
            return e.getMsg();
        }
        return null;
    }
}
